import { message } from "antd";
import { get_offer } from "@/app/api/index";
import { StreamConfigurations, SwitchResult, VideoItem } from "./config";

// 定义每个流的统一配置
export interface StreamConfig {
    id: string;
    url?: string;
    duration: number;
    seep: number[][];
    label: string;
    type: string;
}

export { StreamConfigurations }


interface WebRTCManagerCallbacks {
    onStreamReady: (streamId: string, stream: MediaStream) => void;
    onConnectionStateChange: (streamId: string, state: RTCPeerConnectionState) => void;
    onSessionId: (streamId: string, sessionId: number) => void;
    onError: (errorMessage: string, advice?: string) => void;
}

export class WebRTCManager {
    private pcs: Map<string, RTCPeerConnection> = new Map();
    private callbacks: WebRTCManagerCallbacks;
    public sessionIds: Map<string, number> = new Map();

    constructor(callbacks: WebRTCManagerCallbacks) {
        this.callbacks = callbacks;
    }

    public async start(): Promise<void> {
        const offerEndpoints = StreamConfigurations.filter(e => e.url && e.url.length > 0);

        if (offerEndpoints.length === 0) {
            this.callbacks.onError(
                "No RTC URLs are configured.",
                "请检查环境变量 NEXT_PUBLIC_API_URL_ALIAS 等"
            );
            return;
        }

        const connectionPromises = offerEndpoints.map(async (endpoint) => {
            try {
                const pc = new RTCPeerConnection({
                    iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
                });
                this.pcs.set(endpoint.id, pc);

                pc.ontrack = (event) => {
                    if (event.streams && event.streams[0]) {
                        this.callbacks.onStreamReady(endpoint.id, event.streams[0]);
                    }
                };

                pc.onconnectionstatechange = () => {
                    this.callbacks.onConnectionStateChange(endpoint.id, pc.connectionState);
                };

                const offer = await pc.createOffer({
                    offerToReceiveVideo: true,
                    offerToReceiveAudio: true,
                });
                await pc.setLocalDescription(offer);

                const response: any = await get_offer(pc.localDescription!.sdp, endpoint.url);

                if (response && response.sdp && response.type === 'answer') {
                    if (response.sessionid) {
                        this.sessionIds.set(endpoint.id, response.sessionid);
                        this.callbacks.onSessionId(endpoint.id, response.sessionid);

                        // 将 sessionid 存储到 StreamConfigurations 中
                        const configItem = StreamConfigurations.find(item => item.id === endpoint.id);
                        if (configItem) {
                            configItem.sessionid = response.sessionid;
                        }
                    }
                    await pc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: response.sdp }));
                } else {
                    throw new Error(`从服务器接收到的响应无效 ${endpoint.id}`);
                }
            } catch (error) {
                message.error(`流 ${endpoint.id} 启动失败`);
                console.error(`WebRTC 流 ${endpoint.id} 启动失败:`, error);
                this.callbacks.onError(`流 ${endpoint.id} 启动失败`, String(error));
            }
        });
        await Promise.all(connectionPromises);
    }

    public close(): void {
        for (const pc of this.pcs.values()) {
            pc.close();
        }
        this.pcs.clear();
    }
}


export function GetNextSwitchInfo(
    currentTime: number,
    typeFilter?: string,
    currentId: string = 'default',
): SwitchResult {
    const currentItem = StreamConfigurations.find(item => item.id === currentId);
    if (!currentItem) return { item: null, diff: 0, nextStart: null };

    const videoDuration = currentItem.duration || 20;
    const fullCycleDuration = videoDuration * 2; // 正放+倒放的完整周期
    const timeInFullCycle = currentTime % fullCycleDuration;

    // 判断当前是否处于倒放阶段
    const isReverse = timeInFullCycle >= videoDuration;
    const timeInCycle = isReverse ?
        (fullCycleDuration - timeInFullCycle) : // 倒放时，时间轴反向计算
        timeInFullCycle; // 正放时，直接使用

    const seepData = isReverse ? currentItem.seepReverse : currentItem.seep;

    // 1. 判断是否在说话区间
    let currentEnd: number | null = null;
    for (const [start, end] of seepData) {
        if (timeInCycle >= start && timeInCycle <= end) {
            currentEnd = end;
            break;
        }
    }

    // 2. 计算说完本视频后要切换的时间点
    let switchTime = currentTime;
    let waitToEnd = 0;
    if (currentEnd !== null) {
        waitToEnd = currentEnd - timeInCycle;
        switchTime += waitToEnd;
    }

    // 3. 查找下一个视频的下一个说话区间
    let minWait = Infinity;
    let nextItem: VideoItem | null = null;
    let nextStart: number | null = null;

    for (const item of StreamConfigurations) {
        if (typeFilter && item.type !== typeFilter) continue;
        const duration = item.duration || 20;
        const itemFullCycleDuration = duration * 2;
        const itemTimeInFullCycle = switchTime % itemFullCycleDuration;

        // 判断目标视频在切换时间点是否处于倒放状态
        const itemIsReverse = itemTimeInFullCycle >= duration;
        const tInCycle = itemIsReverse ?
            (itemFullCycleDuration - itemTimeInFullCycle) :
            itemTimeInFullCycle;

        const itemSeepData = itemIsReverse ? item.seepReverse : item.seep;
        let found = false;
        for (const [start, end] of itemSeepData) {
            if (start >= tInCycle) {
                const wait = start - tInCycle;
                if (wait < minWait) {
                    minWait = wait;
                    nextItem = item;
                    nextStart = start;
                }
                found = true;
                break;
            }
        }
        // 如果本周期没有，取下一个周期的第一个说话区间
        if (!found) {
            // 如果当前周期没有合适的说话区间，考虑下一个周期
            // 计算到下一个周期开始需要等待的时间
            const waitToCycle = duration - tInCycle;

            // 计算下一个周期开始时的绝对时间点
            const nextCycleAbsoluteTime = switchTime + waitToCycle;
            const nextCycleTimeInFullCycle = nextCycleAbsoluteTime % (duration * 2);
            const nextCycleIsReverse = nextCycleTimeInFullCycle >= duration;
            const nextCycleSeepData = nextCycleIsReverse ? item.seepReverse : item.seep;

            if (nextCycleSeepData.length > 0) {
                // 总等待时间 = 等待周期结束 + 下一个周期第一个说话区间的起点
                const waitInCycle = nextCycleSeepData[0][0];
                const totalWait = waitToCycle + waitInCycle;

                if (totalWait < minWait) {
                    minWait = totalWait;
                    nextItem = item;
                    nextStart = nextCycleSeepData[0][0];
                }
            }
        }
    }
    // 总延迟 = 说完本视频剩余 + 下一个视频等待说话区间
    const totalDelay = waitToEnd + minWait;
    return { item: nextItem, diff: totalDelay, nextStart };
}
